/**
 * @file    vio_main.c
 * @brief   vio sample
 *
 * Copyright (c) 2017 Huawei Tech.Co., Ltd.
 *
 * @author    HiMobileCam Reference Develop Team
 * @date      2019/4/2
 * @version   1.0

 */

#include "hi_appcomm_log.h"
#include "vio_param.h"
#include "hi_hal_screen.h"

#include "hi_mapi_sys.h"

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#define DEV_SNS_MODE_MAX_NUM 4
typedef struct tagPARAM_SENSOR_CONFIG {
    HI_MAPI_SENSOR_ATTR_S   snsAttr;
    HI_FLOAT                maxFrameRate;
    HI_CHAR*                description;
} PARAM_SensorConfig;

typedef struct tagPARAM_VIDEV_CONFIG {
    VI_INTF_MODE_E      inftMode;  /* <Interface mode */
    HI_U32              componentMask[VI_COMPMASK_NUM]; /* <Component mask */
    VI_YUV_DATA_SEQ_E   dateSeq; /* <Input data sequence (only the YUV format is supported) */
    VI_DATA_TYPE_E      inputDataType; /* <Input data type */
} PARAM_VidevConfig;

typedef struct tagPARAM_PIPE_CONFIG {
    HI_U32                 pipeCnt;
    HI_U32                 pipeStartHdl;
    HI_BOOL                 ispBypass;
    VI_PIPE_BYPASS_MODE_E   pipeBypassMode; /* <Pipe Bypass Mode */
    HI_BOOL                 pixelFormatChangedByIve;
} PARAM_PipeConfig;

typedef struct tagPARAM_CAM_CONFIG {
    PARAM_SensorConfig  snsCfg[DEV_SNS_MODE_MAX_NUM];
    PARAM_VidevConfig   viCfg;
    PARAM_PipeConfig    pipeCfg;
} PARAM_CamConfig;

#if defined(HI3519AV100)
#define VO_LCD_HDL 1
#define VO_HDMI_HDL 0
#else
#define VO_LCD_HDL 0
#define VO_HDMI_HDL 0
#endif

#if defined(HI3519AV100) && defined(CONFIG_SNS0_AHD_MIPI) && defined(CONFIG_AHD_NVP6324)
static PARAM_CamConfig s_camCfgs[] = {
    {
         /**sensor mode param */
        {
            {{0, WDR_MODE_NONE,      {1280, 720},  {INPUT_MODE_MIPI,DATA_TYPE_YUV422_8BIT}},25.0,"720P25"},
            {{1, WDR_MODE_NONE,      {1920, 1080}, {INPUT_MODE_MIPI,DATA_TYPE_YUV422_8BIT}},30.0,"1080P30"},
            {},
            {},
        },
        /**vi dev param */
        {VI_MODE_MIPI_YUV422,{0xFF000000,0x00FF0000},VI_DATA_SEQ_VUVU,VI_DATA_TYPE_YUV},
        /**vi pipe param */
        {4,2,HI_FALSE,VI_PIPE_BYPASS_BE,HI_FALSE}
    }
};
#elif defined(HI3559V200) && defined(CONFIG_SNS0_AHD_MIPI) && defined(CONFIG_AHD_NVP6324) && defined(CONFIG_AHD_N3)&& defined(CONFIG_SNS1_BT656)
static PARAM_CamConfig s_camCfgs[] = {
    {
         /**sensor mode param */
        {
            {{0, WDR_MODE_NONE,      {1280, 720},  {INPUT_MODE_MIPI,DATA_TYPE_YUV422_PACKED}},25.0,"720P25"},
            {{1, WDR_MODE_NONE,      {1920, 1080}, {INPUT_MODE_MIPI,DATA_TYPE_YUV422_PACKED}},30.0,"1080P30"},
            {},
            {},
        },
        /**vi dev param */
        {VI_MODE_MIPI,{0xFFFF0000,0x00000000},VI_DATA_SEQ_YVYU,VI_DATA_TYPE_YUV},
        /**vi pipe param */
        {2,0,HI_FALSE,VI_PIPE_BYPASS_BE,HI_TRUE}
    },
    {
         /**sensor mode param */
        {
            {{0, WDR_MODE_NONE,      {1280, 720},  {INPUT_MODE_BT656,DATA_TYPE_YUV422_8BIT}},25.0,"720P25"},
            {{1, WDR_MODE_NONE,      {1920, 1080}, {INPUT_MODE_BT656,DATA_TYPE_YUV422_8BIT}},30.0,"1080P30"},
            {},
            {},
        },
        /**vi dev param */
        {VI_MODE_BT656,{0x00FF0000,0x00000000},VI_DATA_SEQ_UYVY,VI_DATA_TYPE_YUV},
        /**vi pipe param */
        {1,2,HI_TRUE,VI_PIPE_BYPASS_BE,HI_FALSE}
    }
};
#elif defined(HI3559V200) && defined(CONFIG_SNS0_AHD_MIPI) && defined(CONFIG_AHD_NVP6324) && defined(CONFIG_SNS1_IMX307)
static PARAM_CamConfig s_camCfgs[] = {
    {
         /**sensor mode param */
        {
            {{1, WDR_MODE_NONE,      {1920, 1080}, {INPUT_MODE_MIPI,DATA_TYPE_YUV422_PACKED}},30.0,"1080P30"},
            {{1, WDR_MODE_NONE,      {1920, 1080}, {INPUT_MODE_MIPI,DATA_TYPE_YUV422_PACKED}},30.0,"1080P30"},
            {},
            {},
        },
        /**vi dev param */
        {VI_MODE_MIPI,{0xFFFF0000,0x00000000},VI_DATA_SEQ_YVYU,VI_DATA_TYPE_YUV},
        /**vi pipe param */
        {2,0,HI_FALSE,VI_PIPE_BYPASS_BE,HI_TRUE}
    },
    {
         /**sensor mode param */
        {
            {{0, WDR_MODE_NONE,      {1920, 1080},  {INPUT_MODE_MIPI,DATA_TYPE_RAW_10BIT}},30.0,"1080P30"},
            {{0, WDR_MODE_2To1_LINE,      {1920, 1080}, {INPUT_MODE_MIPI,DATA_TYPE_RAW_10BIT}},30.0,"1080P30"},
            {},
            {},
        },
        /**vi dev param */
        {VI_MODE_MIPI,{0xFFF00000,0x00000000},VI_DATA_SEQ_UYVY,VI_DATA_TYPE_RGB},
        /**vi pipe param */
        {1,2,HI_FALSE,VI_PIPE_BYPASS_NONE,HI_FALSE}
    }
};
#endif

#undef CONFIG_SENSOR_CNT
#define CONFIG_SENSOR_CNT sizeof(s_camCfgs)/sizeof(s_camCfgs[0])


static HI_VOID GenerateViVpssMode(MEDIA_ViVpssMode* viVpssMode)
{
    HI_S32 i, j;
    for (i = 0; i < HI_PDT_MEDIA_VCAP_DEV_MAX_CNT; ++i) {
        for (j = 0; j < HI_PDT_MEDIA_VCAPDEV_PIPE_MAX_CNT; ++j) {
            viVpssMode->mode[i][j].enMode = VI_OFFLINE_VPSS_OFFLINE;
        }
    }
}

static HI_VOID GenerateVbCfg(const PARAM_CamConfig* camCfg, const MEDIA_Cfg* mediaCfg, MEDIA_VbCfg* vbCfg)
{
    HI_S32 i;
    HI_S32 vbIdx = 0;
    for (i = 0; i < MIN(CONFIG_SENSOR_CNT, HI_PDT_MEDIA_VCAP_DEV_MAX_CNT); ++i) {
        const HI_MAPI_SENSOR_ATTR_S* snsAttr = &mediaCfg->videoCfg.vcapCfg.devAttr[i].snsAttr;
        vbCfg->commPool[vbIdx].blkSize =
            HI_APPCOMM_ALIGN(snsAttr->stSize.u32Width, 128) * snsAttr->stSize.u32Height * 2 +
            HI_APPCOMM_ALIGN(snsAttr->stSize.u32Height * 24, 128);
        vbCfg->commPool[vbIdx].blkCnt  = camCfg[i].pipeCfg.pipeCnt*8;
        vbIdx++;

        const HI_MAPI_DISP_WINDOW_ATTR_S* dispWndAttr = &mediaCfg->videoOutCfg.dispCfg[0].wndCfg[i].wndAttr;
        vbCfg->commPool[vbIdx].blkSize  =
            HI_APPCOMM_ALIGN(dispWndAttr->stRect.u32Width, 16) * dispWndAttr->stRect.u32Height * 3 / 2 +
            HI_APPCOMM_ALIGN(dispWndAttr->stRect.u32Height * 24, 16);
        vbCfg->commPool[vbIdx].blkCnt  = camCfg[i].pipeCfg.pipeCnt*3;
        vbIdx++;
    }
    vbCfg->maxPoolCnt = vbIdx;

    MLOGI("VBConfigure: \n");
    for (i = 0; i < vbCfg->maxPoolCnt; ++i) {
        MLOGI("  [%d] BlkSize[%u] BlkCnt[%u]\n", i, vbCfg->commPool[i].blkSize, vbCfg->commPool[i].blkCnt);
    }
}

static HI_VOID GenerateVcapAttr(const PARAM_CamConfig* camCfg, const HI_S32 snsModeIdx,MEDIA_VcapDevAttr* devAttr)
{
    devAttr->enable = HI_TRUE;

    devAttr->snsAttr.enWdrMode = camCfg->snsCfg[snsModeIdx].snsAttr.enWdrMode;
    devAttr->snsAttr.stSize.u32Width  = camCfg->snsCfg[snsModeIdx].snsAttr.stSize.u32Width;
    devAttr->snsAttr.stSize.u32Height = camCfg->snsCfg[snsModeIdx].snsAttr.stSize.u32Height;
    devAttr->snsAttr.u32SnsMode = camCfg->snsCfg[snsModeIdx].snsAttr.u32SnsMode;
    devAttr->snsAttr.stInputDevAttr.inputMode = camCfg->snsCfg[snsModeIdx].snsAttr.stInputDevAttr.inputMode;
    devAttr->snsAttr.stInputDevAttr.inputDataType = camCfg->snsCfg[snsModeIdx].snsAttr.stInputDevAttr.inputDataType;

    devAttr->devAttr.stBasSize.u32Width  = camCfg->snsCfg[snsModeIdx].snsAttr.stSize.u32Width;
    devAttr->devAttr.stBasSize.u32Height = camCfg->snsCfg[snsModeIdx].snsAttr.stSize.u32Height;
    devAttr->devAttr.stWDRAttr.enWDRMode = camCfg->snsCfg[snsModeIdx].snsAttr.enWdrMode;
    devAttr->devAttr.stWDRAttr.u32CacheLine =
        ((devAttr->snsAttr.enWdrMode == WDR_MODE_2To1_LINE) ?
        (devAttr->devAttr.stBasSize.u32Height / 2) : devAttr->devAttr.stBasSize.u32Height);
    devAttr->devAttr.enIntfMode = camCfg->viCfg.inftMode;
    devAttr->devAttr.au32ComponentMask[0]= camCfg->viCfg.componentMask[0];
    devAttr->devAttr.au32ComponentMask[1]= camCfg->viCfg.componentMask[1];
    devAttr->devAttr.enDataSeq = camCfg->viCfg.dateSeq;
    devAttr->devAttr.enInputDataType = camCfg->viCfg.inputDataType;
    for(int i = 0; i < camCfg->pipeCfg.pipeCnt; i++)
    {
        MEDIA_VcapPipeAttr* vcapPipeAttr = &devAttr->vcapPipeAttr[i];
        vcapPipeAttr->pipeHdl = camCfg->pipeCfg.pipeStartHdl + i;
        vcapPipeAttr->enable = HI_TRUE;
        vcapPipeAttr->piepType = HI_MAPI_PIPE_TYPE_VIDEO;
        vcapPipeAttr->frameRate.s32SrcFrameRate = -1;
        vcapPipeAttr->frameRate.s32DstFrameRate = -1;
        vcapPipeAttr->compressMode = COMPRESS_MODE_NONE;

        vcapPipeAttr->ispBypass = camCfg->pipeCfg.ispBypass;
        vcapPipeAttr->pipeBypassMode = camCfg->pipeCfg.pipeBypassMode;
        vcapPipeAttr->ispPubAttr.f32FrameRate = MIN(camCfg->snsCfg[snsModeIdx].maxFrameRate, 30.0f);
        vcapPipeAttr->ispPubAttr.stSize.u32Width = camCfg->snsCfg[snsModeIdx].snsAttr.stSize.u32Width;
        vcapPipeAttr->ispPubAttr.stSize.u32Height = camCfg->snsCfg[snsModeIdx].snsAttr.stSize.u32Height;
        vcapPipeAttr->ispPubAttr.enSnsMirrorFlip = ISP_SNS_NORMAL;
        vcapPipeAttr->ispPubAttr.enBayer = BAYER_BUTT;
        vcapPipeAttr->pixelFormatChangedByIve = camCfg->pipeCfg.pixelFormatChangedByIve;

        MEDIA_VcapPipeChnAttr* pipeChnAttr = &vcapPipeAttr->pipeChnAttr[0];
        pipeChnAttr->enable = HI_TRUE;
        pipeChnAttr->pipeChnHdl = 0;
        pipeChnAttr->destSize.u32Width = camCfg->snsCfg[snsModeIdx].snsAttr.stSize.u32Width;
        pipeChnAttr->destSize.u32Height = camCfg->snsCfg[snsModeIdx].snsAttr.stSize.u32Height;
        pipeChnAttr->frameRate.s32SrcFrameRate = -1;
        pipeChnAttr->frameRate.s32DstFrameRate = -1;
        pipeChnAttr->compressMode = COMPRESS_MODE_NONE;
        pipeChnAttr->pixelFormat = HI_MEDIA_PIXEL_FMT_YVU_SEMIPLANAR_420;
        MLOGI("Pipe[%d]Chn[0] destSize[%ux%u]\n",vcapPipeAttr->pipeHdl,
            pipeChnAttr->destSize.u32Width, pipeChnAttr->destSize.u32Height);
    }

    if (devAttr->snsAttr.enWdrMode == WDR_MODE_2To1_LINE) {
        memcpy(&devAttr->vcapPipeAttr[1], &devAttr->vcapPipeAttr[0], sizeof(MEDIA_VcapPipeAttr));
        devAttr->vcapPipeAttr[1].pipeHdl = devAttr->vcapPipeAttr[0].pipeHdl + 1;
    }

}

static HI_VOID GenerateVpssCfg(const MEDIA_VcapDevAttr* vcapDevAttr, MEDIA_VpssAttr* vpssAttr)
{
    vpssAttr->enable = HI_TRUE;
    vpssAttr->vpssAttr.u32MaxW = vcapDevAttr->devAttr.stBasSize.u32Width;
    vpssAttr->vpssAttr.u32MaxH = vcapDevAttr->devAttr.stBasSize.u32Height;
    vpssAttr->vpssAttr.stFrameRate.s32SrcFrameRate = -1;
    vpssAttr->vpssAttr.stFrameRate.s32DstFrameRate = -1;
    vpssAttr->vpssAttr.enPixelFormat = HI_MEDIA_PIXEL_FMT_YVU_SEMIPLANAR_422;
    vpssAttr->vpssAttr.bNrEn = HI_TRUE;
    vpssAttr->vpssAttr.stNrAttr.enNrType = VPSS_NR_TYPE_VIDEO;
    vpssAttr->vpssAttr.stNrAttr.enCompressMode = COMPRESS_MODE_NONE;
    vpssAttr->vpssAttr.stNrAttr.enNrMotionMode = NR_MOTION_MODE_NORMAL;

    MEDIA_VpssPortAttr* vpssPortAttr = &vpssAttr->portAttr[0];
    vpssPortAttr->enable = HI_TRUE;
    vpssPortAttr->portHdl = 0;
    vpssPortAttr->resolution.u32Width = vpssAttr->vpssAttr.u32MaxW;
    vpssPortAttr->resolution.u32Height = vpssAttr->vpssAttr.u32MaxH;
    vpssPortAttr->supportBufferShare = HI_FALSE;
    vpssPortAttr->frameRate.s32SrcFrameRate = -1;
    vpssPortAttr->frameRate.s32DstFrameRate = -1;
    vpssPortAttr->videoFormat = VIDEO_FORMAT_LINEAR;
    vpssPortAttr->pixelFormat = HI_MEDIA_PIXEL_FMT_YVU_SEMIPLANAR_420;
}

static HI_VOID UpdateVpssPortAttr(PARAM_DisplayType dispType,
                                  const MEDIA_DispWndCfg* dispWndCfg,
                                  MEDIA_VpssPortAttr* vpssPortAttr)
{
    /* update vpsschn handle if scale down */
    if (dispWndCfg->wndAttr.stRect.u32Width < vpssPortAttr->resolution.u32Width) {
        vpssPortAttr->portHdl = 1;
    }
    if (dispType == PARAM_DISPLAY_TYPE_LCD) {
#if defined(CONFIG_SCREEN) && defined(CONFIG_VERTICAL_SCREEN)
        vpssPortAttr->resolution.u32Width  = dispWndCfg->wndAttr.stRect.u32Height;
        vpssPortAttr->resolution.u32Height = dispWndCfg->wndAttr.stRect.u32Width;
#else
        vpssPortAttr->resolution.u32Width  = dispWndCfg->wndAttr.stRect.u32Width;
        vpssPortAttr->resolution.u32Height = dispWndCfg->wndAttr.stRect.u32Height;
#endif
    } else {
        vpssPortAttr->resolution.u32Width  = dispWndCfg->wndAttr.stRect.u32Width;
        vpssPortAttr->resolution.u32Height = dispWndCfg->wndAttr.stRect.u32Height;
    }
}

static HI_VOID GenerateHdmiDisplayCfg(MEDIA_DispCfg *dispCfg, SIZE_S *dispSize)
{
    dispCfg->dispAttr.stPubAttr.u32BgColor = 0xff;
    dispCfg->dispAttr.stPubAttr.enIntfType = VO_INTF_HDMI;
    dispCfg->dispAttr.stPubAttr.enIntfSync = VO_OUTPUT_1080P30;
    dispSize->u32Width  = 1920;
    dispSize->u32Height = 1080;
}
#if defined(CONFIG_SCREEN)
static HI_S32 SwitchLcdIntfType(HI_HAL_SCREEN_LCD_INTF_TYPE_E lcdInftType,
                                VO_INTF_TYPE_E *voIntfType)
{
    switch(lcdInftType) {
        case HI_HAL_SCREEN_LCD_INTF_6BIT:
            *voIntfType = VO_INTF_LCD_6BIT;
            break;
        case HI_HAL_SCREEN_LCD_INTF_8BIT:
            *voIntfType = VO_INTF_LCD_8BIT;
            break;
        case HI_HAL_SCREEN_LCD_INTF_16BIT:
            *voIntfType = VO_INTF_LCD_16BIT;
            break;
        case HI_HAL_SCREEN_LCD_INTF_24BIT:
            *voIntfType = VO_INTF_LCD_24BIT;
            break;
        default:
            MLOGE("Invalid lcd type\n");
            return HI_FAILURE;
    }
    return HI_SUCCESS;
}

static HI_S32 GetLcdDispAttr(HI_HAL_SCREEN_ATTR_S *screenAttr,HI_MAPI_DISP_ATTR_S *dispAttr)
{
    HI_S32 ret = HI_SUCCESS;
    dispAttr->stPubAttr.u32BgColor = 0xff;
    dispAttr->stPubAttr.enIntfSync = VO_OUTPUT_USER;
    switch(screenAttr->enType) {
        case HI_HAL_SCREEN_INTF_TYPE_MIPI:
            dispAttr->stPubAttr.enIntfType = VO_INTF_MIPI;
            break;
        case HI_HAL_SCREEN_INTF_TYPE_LCD:
            ret = SwitchLcdIntfType(screenAttr->unScreenAttr.stLcdAttr.enType,
                                    &dispAttr->stPubAttr.enIntfType);
            HI_APPCOMM_CHECK_RETURN(ret, HI_FAILURE);
            break;
        default:
            MLOGE("Invalid screen type\n");
            return HI_FAILURE;
    }

    dispAttr->stPubAttr.stSyncInfo.bSynm   = 1; /**<sync mode: signal */
    dispAttr->stPubAttr.stSyncInfo.bIop    = 1; /**<progressive display */
    dispAttr->stPubAttr.stSyncInfo.u16Vact = screenAttr->stAttr.stSynAttr.u16Vact;
    dispAttr->stPubAttr.stSyncInfo.u16Vbb  = screenAttr->stAttr.stSynAttr.u16Vbb;
    dispAttr->stPubAttr.stSyncInfo.u16Vfb  = screenAttr->stAttr.stSynAttr.u16Vfb;
    dispAttr->stPubAttr.stSyncInfo.u16Hact = screenAttr->stAttr.stSynAttr.u16Hact;
    dispAttr->stPubAttr.stSyncInfo.u16Hbb  = screenAttr->stAttr.stSynAttr.u16Hbb;
    dispAttr->stPubAttr.stSyncInfo.u16Hfb  = screenAttr->stAttr.stSynAttr.u16Hfb;
    dispAttr->stPubAttr.stSyncInfo.u16Hpw  = screenAttr->stAttr.stSynAttr.u16Hpw;
    dispAttr->stPubAttr.stSyncInfo.u16Vpw  = screenAttr->stAttr.stSynAttr.u16Vpw;
    dispAttr->stPubAttr.stSyncInfo.bIdv    = screenAttr->stAttr.stSynAttr.bIdv;
    dispAttr->stPubAttr.stSyncInfo.bIhs    = screenAttr->stAttr.stSynAttr.bIhs;
    dispAttr->stPubAttr.stSyncInfo.bIvs    = screenAttr->stAttr.stSynAttr.bIvs;

    dispAttr->stUserInfoAttr.stUserInfo.u32PreDiv   = 1;
    dispAttr->stUserInfoAttr.stUserInfo.bClkReverse = screenAttr->stAttr.stClkAttr.bClkReverse;
    dispAttr->stUserInfoAttr.stUserInfo.u32DevDiv   = screenAttr->stAttr.stClkAttr.u32DevDiv;
    dispAttr->stUserInfoAttr.u32DevFrameRate        = screenAttr->stAttr.u32Framerate;
    if (screenAttr->stAttr.stClkAttr.enClkType == HI_HAL_SCREEN_CLK_TYPE_LCDMCLK) {
        dispAttr->stUserInfoAttr.stUserInfo.stUserIntfSyncAttr.enClkSource = VO_CLK_SOURCE_LCDMCLK;
        dispAttr->stUserInfoAttr.stUserInfo.stUserIntfSyncAttr.u32LcdMClkDiv = screenAttr->stAttr.stClkAttr.u32OutClk;
    } else if (screenAttr->stAttr.stClkAttr.enClkType == HI_HAL_SCREEN_CLK_TYPE_PLL) {
        dispAttr->stUserInfoAttr.stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Fbdiv =
            screenAttr->stAttr.stClkAttr.stClkPll.u32Fbdiv;
        dispAttr->stUserInfoAttr.stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Frac =
            screenAttr->stAttr.stClkAttr.stClkPll.u32Frac;
        dispAttr->stUserInfoAttr.stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Refdiv =
            screenAttr->stAttr.stClkAttr.stClkPll.u32Refdiv;
        dispAttr->stUserInfoAttr.stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Postdiv1 =
            screenAttr->stAttr.stClkAttr.stClkPll.u32Postdiv1;
        dispAttr->stUserInfoAttr.stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Postdiv2 =
            screenAttr->stAttr.stClkAttr.stClkPll.u32Postdiv2;
    }
    return HI_SUCCESS;
}


static HI_S32 GetLcdScreenAttr(HI_MAPI_DISP_ATTR_S *dispAttr, HI_MAPI_DISP_VIDEOLAYER_ATTR_S *videoLayerAttr)
{
    HI_S32 ret = HI_SUCCESS;
    HI_HAL_SCREEN_ATTR_S screenAttr = {0};
    ret = HI_HAL_SCREEN_GetAttr(HI_HAL_SCREEN_IDX_0, &screenAttr);
    HI_APPCOMM_CHECK_RETURN(ret, HI_FAILURE);
    ret = GetLcdDispAttr(&screenAttr,dispAttr);

    videoLayerAttr->u32VLFrameRate = screenAttr.stAttr.u32Framerate;
    videoLayerAttr->stImageSize.u32Width  = screenAttr.stAttr.u32Width;
    videoLayerAttr->stImageSize.u32Height = screenAttr.stAttr.u32Height;
    return HI_SUCCESS;
}
#endif

static HI_S32 GenerateLcdDisplayCfg(MEDIA_DispCfg *dispCfg, SIZE_S *dispSize)
{
#if defined(CONFIG_SCREEN)
    HI_S32 ret = HI_SUCCESS;
    ret = GetLcdScreenAttr(&dispCfg->dispAttr, &dispCfg->videoLayerAttr);
    HI_APPCOMM_CHECK_RETURN(ret, HI_FAILURE);
    dispSize->u32Width  = dispCfg->videoLayerAttr.stImageSize.u32Width;
    dispSize->u32Height = dispCfg->videoLayerAttr.stImageSize.u32Height;
    dispCfg->videoLayerAttr.u32BufLen = 3;

    dispCfg->cscAttr.enable = HI_TRUE;
    dispCfg->cscAttr.cscAttr.stVoCSC.u32Contrast = 50;
    dispCfg->cscAttr.cscAttr.stVoCSC.u32Hue = 50;
    dispCfg->cscAttr.cscAttr.stVoCSC.u32Luma = 50;
    dispCfg->cscAttr.cscAttr.stVoCSC.u32Satuature = 50;
    dispCfg->cscAttr.cscAttr.stVoCSC.enCscMatrix = VO_CSC_MATRIX_BT601_TO_RGB_PC;
#endif
    return HI_SUCCESS;
}
static HI_VOID GetDisplayWindowAttr(HI_S32 dispWndCnt,HI_S32 dispWndIndex,SIZE_S* dispSize, MEDIA_DispWndCfg *dispWndCfg)
{
    dispWndCfg->wndHdl = dispWndIndex;
    if (dispWndCnt == 1) {
        dispWndCfg->wndAttr.stRect.s32X = 0;
        dispWndCfg->wndAttr.stRect.s32Y = 0;
        dispWndCfg->wndAttr.stRect.u32Width = dispSize->u32Width;
        dispWndCfg->wndAttr.stRect.u32Height = dispSize->u32Height;
    }else if (dispWndCnt > 1 && dispWndCnt <= 4) {
        if (dispWndCfg->rotation == ROTATION_90) {
            dispWndCfg->wndAttr.stRect.s32X = (dispWndIndex >= 2) ? HI_APPCOMM_ALIGN(dispSize->u32Width / 2, 2) : 0;
            dispWndCfg->wndAttr.stRect.s32Y = ((dispWndIndex % 2) != 0) ? HI_APPCOMM_ALIGN(dispSize->u32Height / 2, 2): 0;
        } else {
            dispWndCfg->wndAttr.stRect.s32X = ((dispWndIndex % 2) != 0) ? HI_APPCOMM_ALIGN(dispSize->u32Width / 2, 2): 0;
            dispWndCfg->wndAttr.stRect.s32Y = (dispWndIndex >= 2) ? HI_APPCOMM_ALIGN(dispSize->u32Height / 2, 2) : 0;
        }
        dispWndCfg->wndAttr.stRect.u32Width = HI_APPCOMM_ALIGN(dispSize->u32Width / 2, 2);
        dispWndCfg->wndAttr.stRect.u32Height = HI_APPCOMM_ALIGN(dispSize->u32Height / 2, 2);
    }
    MLOGI("  Wnd[%d] hdl[%d] Pos[%d,%d] Size[%ux%u] Rotation[%d]\n",
        dispWndIndex, dispWndCfg->wndHdl, dispWndCfg->wndAttr.stRect.s32X, dispWndCfg->wndAttr.stRect.s32Y,
        dispWndCfg->wndAttr.stRect.u32Width, dispWndCfg->wndAttr.stRect.u32Height,dispWndCfg->rotation);

    dispWndCfg->wndAttr.u32Priority = 0;

}
static HI_VOID GenerateDisplayCfg(PARAM_DisplayType dispType, MEDIA_VideoCfg *videoCfg, MEDIA_DispCfg *dispCfg)
{
    SIZE_S dispSize = {0,0};
    if (dispType == PARAM_DISPLAY_TYPE_HDMI) {
        GenerateHdmiDisplayCfg(dispCfg, &dispSize);
    } else if (dispType == PARAM_DISPLAY_TYPE_LCD) {
        GenerateLcdDisplayCfg(dispCfg, &dispSize);
    } else {
        return;
    }

    dispCfg->enable = HI_TRUE;
    dispCfg->dispHdl = ((dispType == PARAM_DISPLAY_TYPE_LCD)?VO_LCD_HDL:VO_HDMI_HDL);

    dispCfg->videoLayerAttr.u32BufLen = 3;
    MLOGI("disp size[%ux%u]\n", dispSize.u32Width, dispSize.u32Height);


    HI_S32 i;
    int dispWndCnt = 0;
    for(int i = 0; i < MIN(CONFIG_SENSOR_CNT, HI_PDT_MEDIA_VCAP_DEV_MAX_CNT); i++){
        dispWndCnt += s_camCfgs[i].pipeCfg.pipeCnt;
    }

    for (i = 0; i < dispWndCnt; ++i) {
        MEDIA_DispWndCfg* dispWndCfg = &dispCfg->wndCfg[i];
        dispWndCfg->enable = HI_TRUE;

        if (dispType == PARAM_DISPLAY_TYPE_LCD) {
#if defined(CONFIG_SCREEN) && defined(CONFIG_VERTICAL_SCREEN)
            dispWndCfg->rotation = ROTATION_90;
#else
            dispWndCfg->rotation = ROTATION_0;
#endif
        } else {
            dispWndCfg->rotation = ROTATION_0;
        }
        GetDisplayWindowAttr(dispWndCnt,i,&dispSize,dispWndCfg);

        dispWndCfg->bindedMod = MEDIA_VIDEOMOD_VPSS;
        dispWndCfg->modHdl = videoCfg->vprocCfg.vpssAttr[i].vpssHdl;
        UpdateVpssPortAttr(dispType, dispWndCfg, &videoCfg->vprocCfg.vpssAttr[i].portAttr[0]);
        dispWndCfg->chnHdl = videoCfg->vprocCfg.vpssAttr[i].portAttr[0].portHdl;
    }
}

HI_S32 HI_PARAM_GetSnsSeqCnt(HI_VOID)
{
    return DEV_SNS_MODE_MAX_NUM;
}

HI_S32 HI_PARAM_GetSnsSeqDesc(HI_S32 index, HI_CHAR *buff, HI_U32 buffLen)
{
    HI_APPCOMM_CHECK_POINTER(buff, HI_FAILURE);
    if (index < 0 || index >= HI_PARAM_GetSnsSeqCnt()) {
        MLOGE("invalid sensor seq index[%d] out of range[0, %d]\n",
            index, HI_PARAM_GetSnsSeqCnt() - 1);
        return HI_FAILURE;
    }

    PARAM_SensorConfig* snsCfg = NULL;
    HI_S32 i;
    HI_S32 buffOffset = 0;
    for (i = 0; i < MIN(CONFIG_SENSOR_CNT, HI_PDT_MEDIA_VCAP_DEV_MAX_CNT); ++i) {
        snsCfg = &s_camCfgs[i].snsCfg[index];
        if(snsCfg->snsAttr.stSize.u32Width == 0)
        {
            memset(buff,'\0',buffLen);
            continue;
        }
        snprintf(buff + buffOffset, buffLen, "%s%s[%ux%u(%u) %f%s]",
            (i == 0) ? "" : " / ", snsCfg->description,
            snsCfg->snsAttr.stSize.u32Width, snsCfg->snsAttr.stSize.u32Height, snsCfg->snsAttr.u32SnsMode,
            snsCfg->maxFrameRate, (snsCfg->snsAttr.enWdrMode == WDR_MODE_NONE) ? "" : " WDR");
        buffOffset = strnlen(buff, buffLen - 1);
    }
    return HI_SUCCESS;
}

HI_S32 HI_PARAM_GetMediaCfg(HI_S32 snsSeqIdx, PARAM_DisplayType dispType, MEDIA_Cfg *mediaCfg)
{
    HI_APPCOMM_CHECK_POINTER(mediaCfg, HI_FAILURE);
    if (snsSeqIdx < 0 || snsSeqIdx >= HI_PARAM_GetSnsSeqCnt()) {
        MLOGE("invalid sensor seq index[%d] out of range[0, %d]\n",
            snsSeqIdx, HI_PARAM_GetSnsSeqCnt() - 1);
        return HI_FAILURE;
    }
    memset(mediaCfg, 0, sizeof(MEDIA_Cfg));

    /* vi vpss mode */
    GenerateViVpssMode(&mediaCfg->viVpssMode);

    HI_S32 i;
    PARAM_SensorConfig* snsCfg = NULL;
    for (i = 0; i < MIN(CONFIG_SENSOR_CNT, HI_PDT_MEDIA_VCAP_DEV_MAX_CNT); ++i) {
        snsCfg = &s_camCfgs[i].snsCfg[snsSeqIdx];
        if(snsCfg->snsAttr.stSize.u32Width == 0)
        {
            continue;
        }
        MLOGI("camCfg[%d]: size[%ux%u] mode[%u] maxframerate[%f] wdrmode[%d],CONFIG_SENSOR_CNT[%d]\n",
            i, snsCfg->snsAttr.stSize.u32Width, snsCfg->snsAttr.stSize.u32Height,
            snsCfg->snsAttr.u32SnsMode,snsCfg->maxFrameRate, snsCfg->snsAttr.u32SnsMode,
            CONFIG_SENSOR_CNT);

        /* vcap */
        mediaCfg->videoCfg.vcapCfg.devAttr[i].devHdl = i;
        GenerateVcapAttr(&s_camCfgs[i], snsSeqIdx,&mediaCfg->videoCfg.vcapCfg.devAttr[i]);
        int vpssIdx = 0;
        for(int k = 0; k < i; k++){
            vpssIdx += s_camCfgs[k].pipeCfg.pipeCnt;
        }

        for(int j = 0; j < s_camCfgs[i].pipeCfg.pipeCnt; j++){

            MEDIA_VpssAttr* vpssAttr = &mediaCfg->videoCfg.vprocCfg.vpssAttr[vpssIdx+j];
            vpssAttr->vpssHdl = vpssIdx+j;
            vpssAttr->vcapPipeHdl = mediaCfg->videoCfg.vcapCfg.devAttr[i].vcapPipeAttr[j].pipeHdl;
            vpssAttr->vcapPipeChnHdl = 0;
            GenerateVpssCfg(&mediaCfg->videoCfg.vcapCfg.devAttr[i], vpssAttr);
        }
    }

    /* display */
    GenerateDisplayCfg(dispType, &mediaCfg->videoCfg, &mediaCfg->videoOutCfg.dispCfg[0]);

    /* vb configure */
    GenerateVbCfg(&s_camCfgs[0],mediaCfg, &mediaCfg->vbCfg);

    return HI_SUCCESS;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */

